/* eslint-disable global-require */
/* eslint-disable node/no-unsupported-features/es-syntax */
/* eslint-disable no-underscore-dangle */
const express = require('express')

const router = express.Router()
const _ = require('lodash')
const qs = require('qs')
const EventProxy = require('eventproxy')
const ccap = require('../utils/verifycode')
const { bigImg } = require('../utils/tools')
const mail = require('../utils/email')
const {
  emailCode,
  validEmailCode,
  loginValid,
  // submitGoodsValid,
} = require('../utils/helper')

const dictCache = require('../utils/dictCache')
// const cache = require('../utils/cache')
const {
  Page,
  User,
  Catalog,
  Goods,
  Article,
  Dict,
  // Postage,
} = require('../viewModels')
// 对常见字段格式进行校验
// router.use((req,res,next) => {
//
// })
const dictCa = dictCache.getInstance()
// 找到导航虽在的父集
function findParentNav(url, cata) {
  let curr = null
  cata.forEach((item) => {
    if (item.relativeUrl === url) {
      curr = item
    } else if (item.children.some((sub) => sub.relativeUrl === url)) {
      curr = item
    }
  })
  return curr
}
// 找出路由对应的导航
function findNav(url, cata) {
  let curr = null
  curr = cata.find((sub) => sub.relativeUrl === url && sub.deep === 3)
  if (!curr) {
    curr = cata.find((sub) => sub.relativeUrl === url && sub.deep === 2)
  }
  return curr
}
function findNavById(id, cata) {
  return cata.find((sub) => sub._id.toString() === id.toString())
}
router.use((req, res, next) => {
  const ep = EventProxy.create('cataObj', 'dicts', 'news', (cataObj, dicts, news) => {
    res.locals.catalogs = cataObj.catalogs
    res.locals.cataChild = cataObj.cataChild
    res.locals.products = cataObj.cataChild.find((item) => item.name === 'goods')
    res.locals.currNav = findParentNav(req.path, cataObj.cataChild)
    res.locals.currInfo = findNav(req.path, cataObj.catalogs)
    res.locals.news = news
    const dictObj = _.keyBy(dicts, 'name')
    res.locals.frontInfo = _.keyBy(dictObj, 'name')
    res.locals.webInfo = dictObj.webInfo.value
    next()
  })
  ep.fail(next)
  // 获取前端页面导航 及 网站配置信息
  Catalog.getChildModeByName('front', (err, cataChild, catalogs) => {
    if (err) return ep.emit('error', err)
    ep.emit('cataObj', { cataChild, catalogs })
  })
  Article.findTopArticle('news', 4, ep.done('news'))
  dictCa.getDicts('front', ep.done('dicts'))
})
router.use((req, res, next) => {
  const { user } = req.session
  if (user && user.cart && user.cart.length > 0) {
    res.locals.cartNum = user.cart.reduce((before, item) => before + item.goodsNum, 0)
  } else {
    res.locals.cartNum = 0
  }
  next()
})
// router.get(checkLogin);
router.get('/', (req, res, next) => {
  // console.log(req.session.user,"这里可以取到session");
  const ep = EventProxy.create('dicts',
    (dicts) => {
      const info = _.keyBy(dicts, 'name')
      console.log(info, 'info -- - - ----------------------')
      res.render('index', {
        title: '首页',
        info,
        homeBanner: info.homeBanner.value, // 首页banner
        links: info.links.value, // 友情链接
      })
    })
  ep.fail(next)
  Dict.findByGroup('home', ep.done('dicts'))
})
// 清空缓存内容
router.post('/clearCache', (req, res, next) => {})

// 获取验证码
router.get('/imgCode', (req, res) => {
  const arr = ccap.get()
  req.session.imgCode = `${arr[0]}`
  res.send(arr[1])
})
// 留言发送邮件
router.get('/feedback', (req, res) => {
  res.render('feedback', { title: ' 在线留言' })
})
router.post('/feedback', (req, res) => {
  res.json({
    code: 0,
    message: '发送成功',
  })
})
// 简单页面
router.get('/page/:pageName', (req, res, next) => {
  const curr = res.locals.currInfo
  if (curr.useTpl) {
    res.render(curr.useTpl, {
      title: curr.nameCn,
      nav: curr,
    })
  } else {
    Page.getPageByPathName(req.params.pageName, (err, page) => {
      if (err || !page) {
        return next(err)
      }
      res.render('page', {
        title: page.title,
        page,
        nav: curr,
      })
    })
  }
})
// 文章管理
router.get('/article/list/:type', (req, res, next) => {
  const ep = EventProxy.create('topArticles', 'obj', (topArticles, obj) => {
    obj.topArticles = topArticles
    res.render('article/list', obj)
  })
  ep.fail(next)
  Article.findTopArticle(req.params.type, ep.done('topArticles'))
  Catalog.findByName(req.params.type, (err, catalog) => {
    if (err || !catalog) return ep.emit('error', err || new Error('catalog 没有找到'))
    return Article.findAllByPageCatalogs(
      catalog.name,
      req.query.page,
      10,
      (errArt, obj) => {
        if (errArt) return ep.emit('error', errArt)
        return ep.emit('obj', { title: catalog.nameCn, ...obj })
      },
    )
  })
})
router.get('/article/detail/:id', (req, res, next) => {
  Article.findByIdAddView(req.params.id, (err, article) => {
    if (err) return next(err)
    if (!article) return next()
    res.locals.currInfo = findNavById(article.catalog, res.locals.catalogs)
    res.locals.currNav = findParentNav(res.locals.currInfo.relativeUrl, res.locals.cataChild)
    return Article.findTopArticle(article.catalogName, (errAri, topArticles) => {
      if (errAri) return next(errAri)
      return res.render('article/detail', {
        title: article.title,
        article,
        topArticles,
      })
    })
  })
})
router.get('/goods/index/:product', (req, res, next) => {
  // req.query.catalogsId
  Catalog.getChildrenByName('goods', (err, catalogs) => {
    if (err) return next(err)
    const params = { onSale: 1 }
    if (req.params.product) {
      const catalog = catalogs.find((item) => item.name === req.params.product)
      params.catalogPath = new RegExp(`^${catalog.calPath},${catalog.name}`)
    } else {
      const front = res.locals.frontInfo
      if (front && front.notCatalogShow && front.notCatalogShow.value) {
        const tmpArr = front.notCatalogShow.value.split(',')
        params.catalogId = { $nin: [...tmpArr] }
      }
    }
    if (req.query.search) {
      params.name = new RegExp(req.query.search)
    }
    Goods.findAllByPage(params, req.query.page, 12, (err, obj) => {
      const queryStr = qs.stringify(req.query)
      res.render('goods/index', {
        title: '商品展示', goodTypes: catalogs, queryStr, ...obj,
      })
    })
  })
})
// 商品列表
router.get('/goods/index', (req, res, next) => {
  // req.query.catalogsId
  Catalog.getChildrenByName('goods', (err, catalogs) => {
    if (err) return next(err)
    const params = { onSale: 1 }
    if (req.query.catalog) {
      const catalog = catalogs.find((item) => item.name === req.query.catalog)
      params.catalogPath = new RegExp(`^${catalog.calPath},${catalog.name}`)
    } else {
      const front = res.locals.frontInfo
      if (front && front.notCatalogShow && front.notCatalogShow.value) {
        const tmpArr = front.notCatalogShow.value.split(',')
        params.catalogId = { $nin: [...tmpArr] }
      }
    }
    if (req.query.search) {
      params.name = new RegExp(req.query.search)
    }
    Goods.findAllByPage(params, req.query.page, 12, (err, obj) => {
      const queryStr = qs.stringify(req.query)
      res.render(
        'goods/index',
        {
          title: '商品展示', goodTypes: catalogs, queryStr, ...obj,
        },
      )
    })
  })
})
// 商品详情
router.get('/goods/detail/:id', (req, res, next) => {
  const ep = EventProxy.create(
    'goods',
    'topGoods',
    'newGoods',
    (goods, topGoods, newGoods) => {
      if (!goods) return next()
      res.locals.currInfo = findNavById(goods.catalogId, res.locals.catalogs)
      res.locals.currNav = findParentNav(res.locals.currInfo.relativeUrl, res.locals.cataChild)
      res.render('goods/detail', {
        title: goods.name,
        goods,
        topGoods,
        newGoods,
      })
    },
  )
  ep.fail(next)
  Goods.getHotGoodsByType(1, 4, ep.done('topGoods')) // 推荐产品
  Goods.getHotGoodsByType(3, 4, ep.done('newGoods')) // 新品上市
  Goods.findByIdAddView(req.params.id, ep.done('goods')) // 查找商品及更新访问次数
})

// 个人信息
router.get('/account/accountInfo', loginValid, (req, res, next) => {
  res.render('account/accountInfo', { title: '个人信息' })
})
router.post('/account/accountInfo', loginValid, (req, res, next) => {
  // req.body
  const param = req.body
  User.saveById(req.session.user._id, param, (err, user) => {
    if (err) return next(err)
    req.session.user = user
    req.flash('success', '保存成功')
    res.redirect('/account/accountInfo')
  })
})

router.get('/account/changePwd', loginValid, (req, res, next) => {
  res.render('account/changePwd', { title: '修改密码' })
})
router.post('/account/changePwd', loginValid, (req, res, next) => {
  req
    .checkBody('oldpwd', '原始密码不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('密码错误')
  req
    .checkBody('pwd', '密码不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('密码太短')
  req
    .checkBody('pwdRepeat')
    .notEmpty()
    .isSame(req.body.pwd)
    .withMessage('密码不一致')
  req.asyncValidationErrors().then(
    () => {
      // console.log(req.body)
      // User.findById
      User.findById(req.session.user._id, (err, user) => {
        if (err) return next(err)
        if (user.pwd !== req.body.oldpwd) {
          req.flash('error', '账户名或密码错误')
          return res.redirect('/account/changePwd')
        }
        User.findAndUpdate(user._id, { pwd: req.body.pwd }, (err, newUser) => {
          // console.log(newUser)
          req.flash('success', '修改成功')
          res.redirect('/account/changePwd')
        })
        // req.flash('success', '修改成功')
        // res.redirect('/account/changePwd')
      })
    },
    (errors) => {
      req.flash('error', errors[0].msg)
      res.redirect('/account/changePwd')
    },
  )
})

router.get('/test', (req, res) => {
  res.render('test', { title: '测试' })
})
router.get('/map', (req, res) => {
  res.render('map', { title: '测试' })
})
router.get('/login', (req, res) => {
  res.render('login', { title: '用户登录' })
})
router.post('/login', (req, res, next) => {
  req
    .checkBody('userName', '用户名不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('用户名太短')
  req
    .checkBody('password', '密码不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('密码太短')
  req
    .checkBody('verifyCode', '验证码不能为空')
    .notEmpty()
    .isEqual(req.session.imgCode)
    .withMessage('验证码不正确')
  req.asyncValidationErrors().then(
    () => {
      console.log(req.body)
      User.findByUserName(req.body.userName, (err, user) => {
        if (err) {
          return next(err)
        }
        if (!user) {
          req.flash('error', '账户名或密码错误')
          return res.redirect('/login')
        }
        if (user.isLock === 1) {
          req.flash('error', '账户名未激活')
          return res.redirect('/login')
        }
        if (user.pwd !== req.body.password) {
          req.flash('error', '账户名或密码错误')
          return res.redirect('/login')
        }
        console.log(user, 'user')
        delete user.pwd
        req.session.user = user
        return res.redirect('/account/index')
      })
    },
    (errors) => {
      req.flash('error', errors[0].msg)
      return res.redirect('/login')
    },
  )
})
router.get('/register', (req, res) => {
  res.render('register', { title: '用户注册' })
})
router.get('/activateUser/:code', (req, res, next) => {
  console.log(req.query.email)
  console.log(req.params.code)
  User.findByEmail(req.query.email, (err, user) => {
    if (!user) {
      return next(new Error('无效的用户'))
    }
    if (user.isLock === 0) {
      req.flash('success', '用户已激活')
      res.render('activateUser', { title: '用户激活' })
    }
    if (!user.emailCode) {
      return next(new Error('无效数据'))
    }
    if (validEmailCode(req.query.email, req.params.code, user.emailCode)) {
      User.updateById(
        user._id,
        {
          isLock: 0,
          emailCode: '',
        },
        (err, newUser) => {
          console.log(err, newUser)
          if (err) return next(err)
          req.session.user = newUser
          req.flash('success', '用户验证成功')
          res.render('activateUser', { title: '用户激活' })
        },
      )
    } else {
      req.flash('error', '用户验证失败')
      res.render('activateUser', { title: '用户激活' })
    }
  })
})
router.post('/register', (req, res, next) => {
  req
    .checkBody('userName', '用户名不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('用户名太短')
  req
    .checkBody('pwd', '密码不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('密码太短')
  req
    .checkBody('pwdRepeat')
    .notEmpty()
    .isSame(req.body.pwd)
    .withMessage('密码不一致')
  req
    .checkBody('email', '邮箱不能为空')
    .notEmpty()
    .isEmail()
    .withMessage('邮箱不正确')
  req
    .checkBody('mobile', '手机号不能为空')
    .notEmpty()
    .isMobile()
    .withMessage('手机号码不正确')
  req
    .checkBody('verifyCode', '验证码不能为空')
    .notEmpty()
    .isEqual(req.session.imgCode)
    .withMessage('验证码不正确')
  req.asyncValidationErrors().then(
    () => {
      const codeObj = emailCode(req.body.email)
      const params = req.body
      params.isLock = 1
      params.emailCode = codeObj.code // 生成随机码
      User.create(req.body, (err, user) => {
        if (err) {
          if (
            err.message.indexOf('E11000 duplicate key error collection') > -1
          ) {
            req.flash('error', '用户已注册')
            return res.redirect('/register')
          }
          console.error(err)
          req.flash('error', err.message)
          return res.redirect('/register')
        }
        const tpl = `<h4>欢迎你注册白石山农场</h4>
<p>请点击下面的连接完成注册</p>
<p><a href="http://www.bssfood.com/activateUser/${codeObj.md5Code}?email=${params.email}">激活用户</a>
<p>3个小时有效</p>
</p>`
        // 这里发送邮件给注册的用户
        mail.send(user.email, tpl, '白石山农场帐号注册')
        req.flash(
          'success',
          '注册成功，注册邮件已经发送到你的邮箱，请查收并激活',
        )
        return res.redirect('/register?success=true')
      })
    },
    (errors) => {
      req.flash('error', errors[0].msg)
      return res.redirect('/register')
    },
  )
})
router.get('/emailPwd/:code', (req, res, next) => {
  if (req.query.isChangPwd || req.query.success) {
    return res.render('emailPwd', { title: '重置密码' })
  }
  if (!req.query.email) {
    return next(new Error('无效修改'))
  }
  User.findByEmail(req.query.email, (err, user) => {
    if (!user) {
      return next(new Error('无效的用户'))
    }
    if (!user.emailCode) {
      return next(new Error('密码已重置'))
    }
    console.log(
      req.query.email,
      req.params.code,
      '???',
      user.emailCode,
      '-------',
    )
    if (validEmailCode(req.query.email, req.params.code, user.emailCode)) {
      req.session.changePwd = true
      req.session.userId = user._id
      req.session.code = req.params.code
      res.render('emailPwd', { title: '重置密码', isChangePwd: false })
    } else {
      return next(new Error('超时,验证失败'))
    }
  })
})
// 密码修改
router.post('/emailPwd', (req, res, next) => {
  if (req.session.isChangPwd === 1) {
    return res.redirect(`/emailPwd/${code}?isChangPwd=true`)
  }
  if (!req.session.changePwd || !req.session.userId) {
    return next(new Error('无效操作'))
  }
  req
    .checkBody('pwd', '密码不能为空')
    .notEmpty()
    .isTooShort(6)
    .withMessage('密码太短')
  req
    .checkBody('pwdRepeat')
    .notEmpty()
    .isSame(req.body.pwd)
    .withMessage('密码不一致')
  req
    .checkBody('verifyCode', '验证码不能为空')
    .notEmpty()
    .isEqual(req.session.imgCode)
    .withMessage('验证码不正确')
  req.asyncValidationErrors().then(
    () => {
      const params = req.body
      User.updateById(
        req.session.userId,
        {
          pwd: req.body.pwd,
          emailCode: '',
        },
        (err, user) => {
          if (err) return next(err)
          req.session.isChangPwd = 1
          req.session.changePwd = ''
          req.session.userId = ''
          const { code } = req.session
          return res.redirect(`/emailPwd/${code}?success=true`)
        },
      )
    },
    (errors) => {
      req.flash('error', errors[0].msg)
      return res.redirect('/forget')
    },
  )
})
router.get('/forget', (req, res) => res.render('forget', { title: '忘记密码' }))
router.post('/forget', (req, res, next) => {
  req
    .checkBody('email', '邮箱不能为空')
    .notEmpty()
    .isEmail()
    .withMessage('邮箱不正确')
  req
    .checkBody('verifyCode', '验证码不能为空')
    .notEmpty()
    .isEqual(req.session.imgCode)
    .withMessage('验证码不正确')
  req.asyncValidationErrors().then(
    () => {
      const params = req.body
      User.findByEmail(params.email, (err, user) => {
        if (!user) {
          req.flash('error', '邮箱不存在')
          return res.redirect('/forget')
        }
        const codeObj = emailCode(user.email)
        User.updateById(
          user._id,
          {
            emailCode: codeObj.code,
          },
          (err, user) => {
            // 发送邮件给用户
            const tpl = `<h4>白石山农场重置密码</h4>
<p>点击下方连接重新修改你的密码</p>
<p><a href="http://www.bssfood.com/emailPwd/${codeObj.md5Code}?email=${user.email}">重置密码</a></p><p>重置密码仅3小时有效，请尽快操作</p>`
            mail.send(user.email, tpl, '白石山农场---密码重置').then(() => res.redirect('/forget?success=true'))
          },
        )
      })
    },
    (errors) => {
      req.flash('error', errors[0].msg)
      return res.redirect('/forget')
    },
  )
})
router.get('/logout', loginValid, (req, res) => {
  req.session.user = null
  return res.redirect('/')
})
module.exports = router
